package com.cs.pk.form;


import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.cs.pk.Activator;
import com.cs.pk.codestriker.Activity;
import com.cs.pk.codestriker.GenerateDiff;
import com.cs.pk.codestriker.GetLatestDesc;
import com.cs.pk.codestriker.ModifiedFile;
import com.cs.pk.codestriker.Obsoletes;
import com.cs.pk.codestriker.Projects;
import com.cs.pk.codestriker.Repository;
import com.cs.pk.codestriker.Title;
import com.cs.pk.codestriker.Views;
import com.cs.pk.job.PopulateList;
import com.cs.pk.utils.ClientHttpRequest;
import com.cs.pk.utils.Constants;
import com.cs.pk.utils.Util;
import com.cs.pk.utils.UtilRepository;

public class CodeReviewForm {

	private IWorkbenchWindow parent = null;
	private Text titleBox, email, rEmail, ccMail, descText = null;
	private Table fileTable = null;

	private String obsolete = "";
	private String streamSelected = null;
	private String viewSelected = null;
	private String projectSelected = null;
	private Shell shell = null;


	public CodeReviewForm(IWorkbenchWindow parent) {
		this.parent = parent;
	}

	public void createForm(ImageDescriptor iDescriptor) {
		shell = new Shell(parent.getShell(), SWT.DIALOG_TRIM
				| SWT.PRIMARY_MODAL | SWT.RESIZE);
		shell.setLayout(new GridLayout(1, false));
		shell.setImage(iDescriptor.createImage());
		Rectangle bounds = parent.getShell().getMonitor().getBounds();

		shell.setBounds(bounds.width / 8, bounds.height / 14,
				bounds.width * 3 / 4, bounds.height * 8 / 9);
		createCRView(shell);
		createCRReview(shell);
		createCRFiles(shell);
		statusPanel(shell);
		shell.open();

	}

	private void createCRView(Composite parent) {

		Group view = new Group(parent, SWT.NONE);
		view.setText("ClearCase");
		GridLayout gl = new GridLayout();
		gl.numColumns = 3;
		view.setLayout(gl);
		setSpan(view, 1, 1, GridData.FILL_HORIZONTAL);

		createLabel(view, "View : ");

		Combo viewCombo = new Combo(view, SWT.DROP_DOWN | SWT.READ_ONLY);
		PopulateList.populateComponent(new Views(viewCombo), null);
		setSpan(viewCombo, 2, 1, GridData.FILL_HORIZONTAL);
	
		
		createLabel(view, "Activity : ");
		final Combo activityCombo = new Combo(view, SWT.DROP_DOWN
				| SWT.READ_ONLY);
		activityCombo.setEnabled(false);
		
		setSpan(activityCombo, 1, 1, GridData.FILL_HORIZONTAL);

		Button refresh = new Button(view, SWT.PUSH);
		refresh.setImage(Activator.getImageDescriptor("icons/refresh.gif")
				.createImage());

		viewCombo.addSelectionListener(new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent e) {
			}

			public void widgetSelected(SelectionEvent e) {
				Combo selCombo = (Combo) e.getSource();
				viewSelected = selCombo.getText();
				if (!viewSelected.trim().equals("")) {
					activityCombo.setEnabled(true);
					PopulateList.populateComponent(new Activity(activityCombo),
							viewSelected);
				}else {
					activityCombo.setEnabled(false);
				}
			}

		});

		activityCombo.addSelectionListener(new SelectionListener() {

			public void widgetDefaultSelected(SelectionEvent e) {	}

			public void widgetSelected(SelectionEvent e) {
				Combo actCombo = (Combo) e.getSource();
				String selected = actCombo.getText();
				if (!selected.trim().equals("")) {
					PopulateList.populateComponent(new Title(titleBox),
							selected);
					PopulateList.populateComponent(new ModifiedFile(fileTable),
							selected);
				}
			}

		});

	}

	private void createCRReview(Composite parent) {
		Group review = new Group(parent, SWT.NONE);
		review.setText("Review");

		GridLayout glr = new GridLayout();
		glr.numColumns = 3;
		review.setLayout(glr);
		setSpan(review, 1, 1, GridData.FILL_HORIZONTAL);

		createLabel(review, "Title : ");

		titleBox = new Text(review, SWT.SINGLE | SWT.BORDER);
		setSpan(titleBox, 2, 1, GridData.FILL_HORIZONTAL);

		createLabel(review, "Obsoletes : ");

		Combo obsCombo = new Combo(review, SWT.DROP_DOWN | SWT.READ_ONLY);
		setSpan(obsCombo, 1, 1, GridData.FILL_HORIZONTAL);
		PopulateList.populateComponent(new Obsoletes(obsCombo), new Integer(1));
		obsCombo.addSelectionListener(new SelectionListener() {

			public void widgetDefaultSelected(SelectionEvent e) {}

			public void widgetSelected(SelectionEvent e) {
				Combo actCombo = (Combo) e.getSource();
				if (actCombo.getSelectionIndex() > 0) {
					obsolete = actCombo.getText();
				} else {
					obsolete = "";
				}
			}

		});

		Button refresh = new Button(review, SWT.PUSH);
		refresh.setImage(Activator.getImageDescriptor("icons/refresh.gif")
				.createImage());

		createLabel(review, "Target Stream : ");

		Combo stream = new Combo(review, SWT.DROP_DOWN | SWT.READ_ONLY);
		setSpan(stream, 2, 1, GridData.FILL_HORIZONTAL);
		PopulateList.populateComponent(new Repository(stream), null);
		stream.addSelectionListener(new SelectionListener() {

			public void widgetDefaultSelected(SelectionEvent e) {

			}

			public void widgetSelected(SelectionEvent e) {
				Combo stream = (Combo) e.getSource();
				streamSelected = stream.getText().trim();// UtilRepository.getValueFromRepository(UtilRepository.STREAM_REPOSITORY,
															// stream.getText().trim()).toString();
			}

		});
		createLabel(review, "Project : ");

		Combo project = new Combo(review, SWT.DROP_DOWN | SWT.READ_ONLY);
		setSpan(project, 2, 1, GridData.FILL_HORIZONTAL);
		PopulateList.populateComponent(new Projects(project), null);
		project.addSelectionListener(new SelectionListener() {

			public void widgetDefaultSelected(SelectionEvent e) {}

			public void widgetSelected(SelectionEvent e) {
				Combo stream = (Combo) e.getSource();
				projectSelected = UtilRepository.getValueFromRepository(
						UtilRepository.PROJECT_REPOSITORY,
						stream.getText().trim()).toString();
			}

		});
		createLabel(review, "EmailAddress");

		email = new Text(review, SWT.SINGLE | SWT.BORDER);
		setSpan(email, 2, 1, GridData.FILL_HORIZONTAL);

		Button reviewer = new Button(review, SWT.PUSH);
		reviewer.setText("Reviewers..");

		rEmail = new Text(review, SWT.SINGLE | SWT.BORDER);
		setSpan(rEmail, 2, 1, GridData.FILL_HORIZONTAL);

		Button ccs = new Button(review, SWT.PUSH);
		ccs.setText("CC..");

		ccMail = new Text(review, SWT.SINGLE | SWT.BORDER);
		setSpan(ccMail, 2, 1, GridData.FILL_HORIZONTAL);

		Button checkBox = new Button(review, SWT.CHECK);
		checkBox.setText("Copy ClearQuest");

		setSpan(createLabel(review, "Description :- "), 3, 1,
				GridData.FILL_HORIZONTAL);
		descText = new Text(review, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL
				| SWT.H_SCROLL);
		setSpan(descText, 3, 20, GridData.FILL_BOTH);

	}

	private void createCRFiles(Composite parent) {
		Group files = new Group(parent, SWT.NONE);
		files.setText("Files");
		GridLayout gl = new GridLayout();
		gl.numColumns = 1;
		files.setLayout(gl);
		setSpan(files, 1, 1, GridData.FILL_HORIZONTAL);

		Button refreshFileList = new Button(files, SWT.PUSH);
		refreshFileList.setImage(Activator.getImageDescriptor(
				"icons/refresh.gif").createImage());
		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
		gd.horizontalSpan = 3;
		gd.horizontalAlignment = SWT.END;
		refreshFileList.setLayoutData(gd);

		fileTable = new Table(files, SWT.CHECK | SWT.BORDER | SWT.H_SCROLL
				| SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.HIDE_SELECTION);
		fileTable.setLinesVisible(true);
		fileTable.setHeaderVisible(true);
		setSpan(fileTable, 1, 20, GridData.FILL_BOTH);
		int width = parent.getClientArea().width;
		for (int i = 0; i < tableHeaders().length; i++) {
			TableColumn column = new TableColumn(fileTable, SWT.LEFT);
			column.setText(tableHeaders()[i]);
			if (i == 0) {
				column.setWidth(70);
				width = width - 70;
			} else {
				column.setWidth(width / 2);
			}
		}
		fileTable.pack();
	}

	private void statusPanel(Composite parent) {

		Label label = new Label(parent, SWT.NONE | SWT.BOLD);
		label.setText("Done..");

		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
		gd.horizontalAlignment = GridData.END;
		Button submit = new Button(parent, SWT.PUSH);
		submit.setText("Submit Review");
		submit.setLayoutData(gd);
		submit.addSelectionListener(new SelectionListener() {

			public void widgetDefaultSelected(SelectionEvent e) {
			}

			public void widgetSelected(SelectionEvent e) {
				final int totalChanges = fileTable.getItemCount();

				PlatformUI.getWorkbench().getDisplay().asyncExec(
						new Runnable() {
							public void run() {
								String viewDir = (String) UtilRepository
										.getValueFromRepository(
												UtilRepository.VIEW_REPOSITORY,
												viewSelected);
								GetLatestDesc gld = new GetLatestDesc(
										streamSelected, viewDir);
								for (int i = 0; i < totalChanges; i++) {
									TableItem ti = fileTable.getItem(i);
									if (ti.getChecked()) {
										gld.start(new String[] { ti.getText(1),
												ti.getText(2) });
									}
								}
								GenerateDiff gd = new GenerateDiff(viewDir);
								gd.start(gld.getFileListForDifference());
								submitReview(gd.getDifferences());
							}
						});

			}

		});

	}

	private void submitReview(String differences) {

		String urlString = Activator.getDefault().getPreferenceStore()
				.getString(com.cs.pk.utils.Constants.CODESTRIKERURL);
		if (urlString == null || urlString.trim().equals("")) {
			urlString = Activator.getDefault().getDefaultPreference(
					Constants.CODESTRIKERURL);
		}
		if (formValidation()) {
			try {
				ClientHttpRequest httpPost = new ClientHttpRequest(urlString);

				httpPost.setParameter("format", "xml");
				httpPost.setParameter("action", "submit_new_topic");
				httpPost.setParameter("obsoletes", obsolete);
				httpPost.setParameter("topic_title", titleBox.getText());
				httpPost.setParameter("topic_description", descText.getText());
				httpPost.setParameter("repository", streamSelected);
				httpPost.setParameter("projectid", projectSelected);
				httpPost.setParameter("email", email.getText());
				httpPost.setParameter("reviewers", rEmail.getText());
				httpPost.setParameter("cc", ccMail.getText());
				httpPost.setParameter(".submit", "Create Topic");
				httpPost.setParameter("topic_file", "review.diff",
						new ByteArrayInputStream(differences.getBytes()));
				InputStream is = httpPost.post();
				DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
				Document result = builder.parse(is);
				NodeList projectList = result.getElementsByTagName("result");
				Element project = (Element)projectList.item(0);
				if(!"OK".equalsIgnoreCase(project.getAttribute("status"))) {
					Util.showMessage(project.getTextContent(), "Error:", SWT.ICON_ERROR|SWT.OK);
				}
				
			} catch (IOException e) {
				e.printStackTrace();
			} catch (ParserConfigurationException e) {
				e.printStackTrace();
			} catch (SAXException e) {
				e.printStackTrace();
			}
			shell.setVisible(false);
			shell.dispose();
		}

	}

	private boolean formValidation() {
		boolean validation = true;
		String message = "";
		if ("".equals(titleBox.getText().trim())) {
			message = "Title is missing. Please put a title.";
			validation = false;
		} else if ("".equals(streamSelected)) {
			message = "Please select a target stream.";
			validation = false;
		} else if ("".equals(projectSelected)) {
			message = "Please select a project.";
			validation = false;
		} else if ("".equals(email.getText().trim())) {
			message = "Please specify an email.";
			validation = false;
		} else if ("".equals(rEmail.getText())) {
			message = "Please mention reviewer email.";
			validation = false;
		} else if ("".equals(descText.getText().trim())) {
			if (Util.showMessage(
							"Description is missing.Do you want to continue?",
							"FormValidation: ", SWT.ICON_INFORMATION | SWT.YES
									| SWT.NO) == SWT.NO) {
				return false;
			} 
		} else if ("".equals(ccMail.getText())) {
			if (Util.showMessage(
					"CC field is missing.Do you want to continue?",
					"FormValidation: ", SWT.ICON_INFORMATION | SWT.YES
							| SWT.NO) == SWT.NO) {
		        return false;
	         } 
		}  else if (fileTable.getItemCount()<=0) {
			message = "No file is selected for review.Cann't process for review.";
			validation = false;
		} 

		if(!validation) {
		Util.showMessage(message,
				 "FormValidation: ",SWT.ICON_INFORMATION| SWT.OK);
		}
		return validation;
	}

	private String[] tableHeaders() {
		return new String[] { "Include?", "Version", "File" };
	}

	private Label createLabel(Group g, String text) {
		Label l = new Label(g, SWT.NONE);
		l.setText(text);
		return l;
	}

	private GridData setSpan(Control widget, int horizontalSpan,
			int verticalSpan, int style) {
		GridData gd = new GridData(style);
		gd.horizontalSpan = horizontalSpan;
		gd.verticalSpan = verticalSpan;
		widget.setLayoutData(gd);
		return gd;
	}
	
	public void dispose(){
		shell.dispose();
	}

}
